<?php

namespace App\Common;

use EasySwoole\Redis\Redis;
use EasySwoole\EasySwoole\Config;
use EasySwoole\RedisPool\RedisPool;

/**
 * @description: reids缓存
 */
class RedisCache
{
    /**
     * @description: 获取缓存
     * @param string $key 键名
     * @param Callable $call 缓存不存在时回调函数
     * @param array $args 回调函数的参数
     * @return {*}
     */
    public static function get($key, ?Callable $call = null, ...$args)
    {
        if (Config::getInstance()->getConf('REDIS.cacheEnable')) {
            $result = RedisPool::invoke(function (Redis $redis) use ($key) {
                $data = $redis->get($key);
                if ($data) {
                    $data = json_decode($data, true);
                    if ($data['cache_expire'] && $data['cache_expire'] - time() >= -10) {
                        $redis->del($key);
                        $data = false;
                    }
                }
                return $data;
            });
        } else {
            $result = false;
        }
        if ($result == false && $call) {
            $result = call_user_func($call, ...$args);
            static::set($key, $result);
        } else {
            unset($result['cache_expire']);
        }
        return $result;
    }

    /**
     * @description: 设置缓存
     * @param string $key 键名
     * @param array $data 数据
     * @param int $expire 过期秒数
     * @return {*}
     */
    public static function set(string $key, array $data, int $expire = 0)
    {
        return RedisPool::invoke(function (Redis $redis) use ($key, $data, $expire) {
            if ($expire > 0) {
                $expire += random_int(1, 5);
            }
            $data['cache_expire'] = $expire > 0 ? $expire + time() : null;
            $data = json_encode($data, JSON_UNESCAPED_UNICODE);
            return $redis->set($key, $data, $expire);
        });
    }

    /**
     * @description: 删除缓存
     * @param string|array $key 键名
     * @return {*}
     */
    public static function del($key)
    {
        return RedisPool::invoke(function (Redis $redis) use ($key) {
            return $redis->del($key);
        });
    }

    /**
     * @description: 获取匹配的keys
     * @param string|array $pattern 匹配规则
     * @return {*}
     */
    public static function keys($pattern)
    {
        return RedisPool::invoke(function (Redis $redis) use ($pattern) {
            return $redis->keys($pattern);
        });
    }


    /**
     * 清空缓存
     */
    public static function clean()
    {
        if (Config::getInstance()->getConf('REDIS.cacheEnable')) {
            $result = RedisPool::invoke(function (Redis $redis) {
                $keys  = static::keys('*');
                if ($keys) {
                    foreach ($keys as $key) {
                        static::del($key);
                    }
                }
            });
        }
    }
}